package com.jfinal.enjoy.lexer;

import com.intellij.lexer.FlexLexer;
import com.intellij.psi.tree.IElementType;
import static com.jfinal.enjoy.psi.EnjoyTypes.*;

%%

%class EnjoyFlexLexer
%implements FlexLexer
%unicode
%public
%function advance
%type IElementType
%states LINE_COMMENT, COMMENT_BLOCK, OUTPUT, EXPR

%%

<YYINITIAL> {
  /* 注释 */
  "#--"             { System.out.println("TOKEN: BLOCK_COMMENT_START -> " + yytext()); yybegin(COMMENT_BLOCK); return BLOCK_COMMENT_START; }
  "###"             { System.out.println("TOKEN: LINE_COMMENT_START -> " + yytext()); yybegin(LINE_COMMENT); return LINE_COMMENT_START; }

  /* 输出表达式 */
  "#("              { System.out.println("TOKEN: OUTPUT_START -> " + yytext()); yybegin(OUTPUT); return OUTPUT_START; }

  /* 带表达式的指令，进入表达式状态 */
  "#if"            { System.out.println("TOKEN: IF -> " + yytext()); yybegin(EXPR); return IF; }
  "#else if"         { System.out.println("TOKEN: ELSEIF -> " + yytext()); yybegin(EXPR); return ELSEIF; }
  "#for"            { System.out.println("TOKEN: FOR -> " + yytext()); yybegin(EXPR); return FOR; }
  "#switch"         { System.out.println("TOKEN: SWITCH -> " + yytext()); yybegin(EXPR); return SWITCH; }

  /* 不带表达式的指令 */
  "#else"           { System.out.println("TOKEN: ELSE -> " + yytext()); return ELSE; }
  "#set"            { System.out.println("TOKEN: SET -> " + yytext());yybegin(EXPR); return SET; }
  "#define"         { System.out.println("TOKEN: DEFINE -> " + yytext()); yybegin(EXPR); return DEFINE; }
  "#include"        { System.out.println("TOKEN: INCLUDE -> " + yytext());yybegin(EXPR);return INCLUDE; }
  "#case"           { System.out.println("TOKEN: CASE -> " + yytext()); return CASE; }
  "#default"        { System.out.println("TOKEN: DEFAULT -> " + yytext()); return DEFAULT; }
  "#end"            { System.out.println("TOKEN: END -> " + yytext()); return END; }

  /* 符号 */
  "("               { System.out.println("TOKEN: LPAREN -> " + yytext()); return LPAREN; }
  ")"               { System.out.println("TOKEN: RPAREN -> " + yytext()); return RPAREN; }
  ","               { System.out.println("TOKEN: COMMA -> " + yytext()); return COMMA; }
  ":"               { System.out.println("TOKEN: COLON -> " + yytext()); return COLON; }
  "."               { System.out.println("TOKEN: DOT -> " + yytext()); return DOT; }

  /* 换行 */
  "\r\n" | "\n" | "\r" { System.out.println("TOKEN: NEWLINE -> " + yytext()); return NEWLINE; }

  /* 空白忽略 */
  [ \t]  { System.out.println("TOKEN: WHITESPACE -> " + yytext()); return WHITESPACE; }


  /* 普通文本 */
  [^#\r\n]+         { System.out.println("TOKEN: ENJOY_TEXT_TOKEN -> " + yytext()); return ENJOY_TEXT_TOKEN; }
  "#"               { System.out.println("TOKEN: ENJOY_TEXT_TOKEN(#) -> " + yytext()); return ENJOY_TEXT_TOKEN; } // 单独#防止吞掉
}

/* 表达式状态 */
<EXPR> {
  [ \t\r\n]+          { /* 忽略空白 */ }

  "("                 { System.out.println("TOKEN: LPAREN -> " + yytext()); return LPAREN; }
  ")"                 { System.out.println("TOKEN: RPAREN -> " + yytext()); yybegin(YYINITIAL); return RPAREN; }
  ","                 { System.out.println("TOKEN: COMMA -> " + yytext()); return COMMA; }
  ":"                 { System.out.println("TOKEN: COLON -> " + yytext()); return COLON; }
  "."                 { System.out.println("TOKEN: DOT -> " + yytext()); return DOT; }
  "="                 { System.out.println("TOKEN: ASSIGN_OP -> " + yytext()); return ASSIGN_OP; }

  "==" | "!=" | "<=" | ">=" | "<" | ">"  { System.out.println("TOKEN: COMPARE_OP -> " + yytext()); return COMPARE_OP; }
  "&&"                { System.out.println("TOKEN: LOGIC_AND -> " + yytext()); return LOGIC_AND; }
  "||"                { System.out.println("TOKEN: LOGIC_OR -> " + yytext()); return LOGIC_OR; }
  "+" | "-"           { System.out.println("TOKEN: ADDITIVE_OP -> " + yytext()); return ADDITIVE_OP; }
  "*" | "/"           { System.out.println("TOKEN: MULTIPLICATIVE_OP -> " + yytext()); return MULTIPLICATIVE_OP; }

  "\"([^\"\\\\\n]|\\\\.)*\"" { System.out.println("TOKEN: STRING_LITERAL -> " + yytext()); return STRING_LITERAL; }
  [0-9]+              { System.out.println("TOKEN: NUMBER -> " + yytext()); return NUMBER; }
  "true" | "false"    { System.out.println("TOKEN: BOOLEAN -> " + yytext()); return BOOLEAN; }
  "null"              { System.out.println("TOKEN: NULL -> " + yytext()); return NULL; }
  [a-zA-Z_][a-zA-Z0-9_]*  { System.out.println("TOKEN: IDENT -> " + yytext()); return IDENT; }

  /* 兜底，表达式里不认识的字符也必须消费 */
  .                   { System.out.println("TOKEN: UNKNOWN(EXPR) -> " + yytext()); return ENJOY_TEXT_TOKEN; }

  /* EOF防止死循环 */
  <<EOF>>             { yybegin(YYINITIAL); return null; }
}



<COMMENT_BLOCK> {
  "--#"               { System.out.println("TOKEN: BLOCK_COMMENT_END -> " + yytext()); yybegin(YYINITIAL); return BLOCK_COMMENT_END; }
  [^-]+               { System.out.println("TOKEN: BLOCK_COMMENT_CONTENT -> " + yytext()); return BLOCK_COMMENT_CONTENT; }
  "-"                 { System.out.println("TOKEN: BLOCK_COMMENT_CONTENT(-) -> " + yytext()); return BLOCK_COMMENT_CONTENT; }
  <<EOF>>             { yybegin(YYINITIAL); return null; }
}

<LINE_COMMENT> {
  [^\r\n]+            { System.out.println("TOKEN: LINE_COMMENT_CONTENT -> " + yytext()); return LINE_COMMENT_CONTENT; }
  "\r\n" | "\n" | "\r" { System.out.println("TOKEN: NEWLINE -> " + yytext()); yybegin(YYINITIAL); return NEWLINE; }
  <<EOF>>             { yybegin(YYINITIAL); return null; }
}

<OUTPUT> {
  [^)]+               { System.out.println("TOKEN: JAVA_EXPR -> " + yytext()); return JAVA_EXPR; }
  ")"                 { System.out.println("TOKEN: RPAREN -> " + yytext()); yybegin(YYINITIAL); return RPAREN; }
  <<EOF>>             { yybegin(YYINITIAL); return null; }
}